/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.jefb.sec.service.impl;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.jefb.dao.ICommonDao;
import org.jefb.entity.RoleEntity;
import org.jefb.entity.UserEntity;
import org.jefb.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public class CustomAuthenticationProvider implements AuthenticationProvider{
	
	@Autowired
	private IUserService userService;
	@Autowired
	private ICommonDao commonDao;
	
	private static ShaPasswordEncoder encoder = new ShaPasswordEncoder(256);
	
	public Authentication authenticate(Authentication authentication)
			throws AuthenticationException {
		String principal = (String) authentication.getPrincipal();
        String password = (String) authentication.getCredentials();
        
        UserEntity example = new UserEntity();
        example.setUsername(principal);
        List<UserEntity> users = commonDao.findByExample(example);
        //UserEntity user = authorityDAO.findUserByUsername(principal);
        
        if(users==null || users.isEmpty()){
        	throw new AuthenticationCredentialsNotFoundException("Username " + principal + " not found!");
        }
        UserEntity user = users.get(0);
        
        Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        Collection<RoleEntity> roles = userService.getRoles(user);
        authorities.addAll(roles);
        if (user.getUsername().equals(principal) && user.getPassword().equals(encoder.encodePassword(password, null))) {
        	//fetch user session
//        	WebApplicationContext currentWebApplicationContext = ContextLoader.getCurrentWebApplicationContext();
//        	UserSessionService userSession = (UserSessionService)currentWebApplicationContext.getBean("userSession");
//        	userSession.setUserEntity(user);
//        	userSession.setUsername(user.getUsername());
//        	userSession.setLoggedIn(true);
        	//TODO load user permissions
        	
            return new UsernamePasswordAuthenticationToken(principal,
                    password,
                    authorities
                    );
        }
        
        throw new BadCredentialsException("Username/Password does not match for " + principal);
	}

	public boolean supports(Class<? extends Object> authentication) {
		return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
	}

	public void setUserService(IUserService userService) {
		this.userService = userService;
	}

	public IUserService getUserService() {
		return userService;
	}

	public void setCommonDao(ICommonDao commonDao) {
		this.commonDao = commonDao;
	}

	public ICommonDao getCommonDao() {
		return commonDao;
	}

}
